<?php
/*******************************************************************************
 * $Date:: Jan 12, 2011 9:27:18 AM                                              $
 * $Revision:                                                                  $
 * $Author:: Tuan Duong                                                        $
 * $Comment::                                                                  $
 ******************************************************************************/ 
/**
 * Description here...
 * 
 * @package Lua
 * @subpackage Builder
 * @author Tuan Duong <bacduong[at]gmail[dot]com>
 * @version 
 */

abstract class Lua_Test_Builder_Abstract
{
    /**
     * @var array
     */
    protected $defaults = array();
    
    /**
     * @var string
     */
    protected $tableName = null;
    
    /**
     * @var Lua_Table_Base
     */
    protected $table = null;
    
    /**
     * @var Lua_Test_Factory
     */
    protected $factory;

    public function __construct()
    {
        $this->defineDefaults();
    }

    abstract protected function defineDefaults();
    
    /**
     * Get Bean name from this object
     * @return string
     */
    protected final function getBeanClassName()
    {
        $tableName = $this->getTableName();
        return 'Lua_Bean_' . Lua_Util_Common::toCamelCase($tableName, true);
    }

    /**
     * Get table name from this object
     * @return string
     */
    protected final function getTableName()
    {
        if ($this->tableName == null) {
            $className = get_class($this);
            $namespace = 'Lua_Test_Builder_';
            if (strncasecmp($namespace, $className, strlen($namespace)) == 0) {
                $className = substr($className, strlen($namespace));
            }
            $this->tableName = Lua_Util_Common::fromCamelCase($className);
        }

        return $this->tableName;
    }

    /**
     * @return Lua_Table_Base
     */
    protected final function getTable()
    {
        if ($this->table == null) {
            $this->table = new Lua_Table_Base($this->getTableName());
        }
        
        return $this->table;
    }
    
    protected function preSave(Lua_Bean_Abstract $bean) { }

    protected function postSave(Lua_Bean_Abstract $bean) { }

    /**
     * @param Lua_Bean_Abstract $bean
     */
    protected function saveToDb(Lua_Bean_Abstract $bean)
    {
        $id = $this->getTable()->save($bean);
        $bean->id = $id;
    }

    /**
     * @param array $data
     * @return Lua_Bean_Abstract
     */
    protected final function saveData($data)
    {
        $beanClassName = $this->getBeanClassName();
        $bean = new $beanClassName();
        /* @var $bean Lua_Bean_Abstract */
        $bean->bindData($data);
        $this->preSave($bean);
        $this->saveToDb($bean);
        $this->postSave($bean);

        return $bean;
    }

    /**
     * @param array $extras
     * @return Lua_Bean_Abstract
     */
    public final function create(array $extras = array())
    {
        $fields = array_merge($this->defaults, $extras);

        $data = array();
        foreach ($fields as $name => $defaultValue) {
            if ($defaultValue instanceof Lua_Test_Builder_Dependency) {
                $parentData = $this->getFactory()->create(
                        $defaultValue->getName(), $defaultValue->getExtras());
                $value = $parentData[$defaultValue->getForeignColumn()];
            } elseif ($defaultValue instanceof Lua_Test_Builder_Sequence) {
                $sequence = $this->getFactory()->getSequence($defaultValue->getName());
                if ($defaultValue->getFormat() == null) {
                    $value = $sequence;
                } else {
                    $value = sprintf($defaultValue->getFormat(), $sequence);
                }
            } else {
                $value = $defaultValue;
            }
            $data[$name] = $value;
        }

        return $this->saveData($data);
    }
    
	/**
     * @return Lua_Test_Factory $factory
     */
    public function getFactory()
    {
        return $this->factory;
    }

	/**
     * @param Lua_Test_Factory $factory
     */
    public function setFactory(Lua_Test_Factory $factory)
    {
        $this->factory = $factory;
    }

}